#ifndef EXCHANGE_INTEROP_SHAPE_H
#define EXCHANGE_INTEROP_SHAPE_H

// #pragma once

#include <sstream>
#include <unordered_map>
#include <vector>
// #include "nlohmann/json.hpp"
#include "topology/TopoShape.hpp"

namespace  AMCAX::Exchange {

/// @ingroup Material
/// @brief Primaryily used to define material information,including ,color,texture,and other related details.
/// 
class InterOpMaterial
{
public:
    InterOpMaterial() = default;
    /// @brief Construct a new Exchange Material object using color
    /// 
    /// @param[in] color:  The color information may be represented in hexadecimal format or color names.
    /// @param[out] NONE
    /// @return NONE
    /// @retval NONE
    /// @note NONE
    /// @see NONE
    InterOpMaterial(std::string color):color_(color){} ;
    /// @brief Get the Color object
    /// 
    /// @param[in] NONE
    /// @param[out] Color information
    /// @return Maybe hexadecimal format or color names.
    /// @retval NONE
    /// @note NONE
    /// @see NONE
    std::string GetColor() {
        return color_ ;
    } ;
public:
    /// The name of the material
    std::string name ;
    /// The color of the material such as  #335577 or red
    std::string mat_color_ ; 
    /// The color of the material such as  #335577 or red
    std::string color_ ; 
    /// The texture information , which may be a URL of an image or a base64 string.
    std::string texture ;
    /// The information of the ambient light ,which may be represented in hexadecimal format or other ways. such as #ffffff
    std::string ambient ; 
    /// The information of the diffuse light ,which may be represented in hexadecimal format or other ways. such as #ffffff
    std::string diffuse ; 
    /// The information of the emissive light ,which may be represented in hexadecimal format or other ways. such as #ffffff
    std::string emissive ;
    /// The information of the specular light ,which may be represented in hexadecimal format or other ways. such as #ffffff
    std::string specular ; 
    /// The shininess of the ambient light information
    double shininess ; 
    /// The transparency of the material ,which is a value between 0.0 and 1.0.
    double transparency ; 

    bool explicit_color = false;

public:
    /// @brief The split representation of RGBA
    /// 
    /// @param[in] rgba: The input hexadecimal RGBA string
    /// @param[out] rgb: The output RGB string
    /// @param[out] op: The output opacity value
    /// @return NONE
    /// @retval NONE
    /// @note NONE
    /// @see NONE
    static void SplitRgba(const std::string& rgba, std::string& rgb, double& op)
    {
        if (rgba.size() != 9) {
            rgb = rgba;
            op = 0.;
            return;
        }

        rgb = rgba.substr(0, 7);

        unsigned int tp;
        std::stringstream ss;
        ss << std::hex << rgba.substr(7);
        ss >> tp;
        op = tp / 255.0f;
    }
} ;

/// @ingroup Exchange
/// @brief Defines the information of the model, including the topology and some materal details.
/// 
class  InterOpObject
{
    
public:
    InterOpObject(std::string outShapeId ):id(outShapeId){
        this->sortId = 0;
    } ;
    /// @brief  Under Exchange ,there may be many sub-Exchanges mounted,This is used to add sub-Exchanges.
    /// 
    /// @param[in] child: The sub-Exchange to be added
    /// @param[out] NONE
    /// @return  NONE
    /// @retval NONE
    /// @note NONE
    /// @see NONE
    void AddChild(std::shared_ptr<InterOpObject> child) 
    {
        this->childs.push_back(child) ;
    };
public:
    /// The information of the topology
    AMCAX::TopoShape shape;
    /// The name of the model
    std::string name ;
    /// The information of the sub-object
    std::vector<std::shared_ptr<InterOpObject>> childs ;
    /// The information of the material
    std::unordered_map<AMCAX::TopoShape,InterOpMaterial> materials ;
    /// The persistent id. step files do not contain IDs,so we need to generate them during import. 
    std::string id ; 
    /// NOTE: GeomBox（Empty nodes in step files are generally of this type）, Part::Feature(Non-Empty nodes in step files are generally based on th "Part" prefix), etc.
    std::string type ; 
    /// ref: https://udb04vpwa9.feishu.cn/wiki/J56NwEDgPiUyHyk6evmcwc7qneh#FGdEdvS4DoTiaTxlA4mcMNClnFb 中的特征命令
    // nlohmann::json parameters ; 
    /// The visibility indicator of the model 
    bool visibility = true;
    /// NOTE: 特征操作用的，如圆角基于那个方块做的 ，则base_id为该方块的id
    /// If it is a feature, the baseId is the id of the base shape.
    std::string baseId ;
    /// NOTE: CAD特征的关联关系，圆角特征是从方块创建的。prelink指向方块的信息。这个特征生成可能依赖多个特征
    /// NOTE: 参数化建模，每一步都要重建，所以依赖这个,用于重建 -> 利用有向无环图
    /// If it is a feature, this refers to the feature informatiion that was relied upon when generating the feature.
    std::vector<std::string> prelinks ;
    // NOTE: 某个特征被那些特征依赖过
    // NOTE: 参数化建模，每一步都要重建，所以依赖这个,用于重建 -> 利用有向无环图
    /// If it is a feature , this refers to the features that rely on the current feature.
    std::vector<std::string> outlinks ;
    
    /// Primarily used for sorting.
    int sortId;
} ;
}

#endif // EXCHANGE_INTEROP_SHAPE_H